#include"socket.hpp"

#include"Epoller.hpp"

#include<sys/epoll.h>

class epollserver
{
public:
    epollserver()
    {
    }

    void init()
    {
        _sk.my_socket();
        _sk.my_bind("0.0.0.0", 8080);
        _sk.my_listen();
        _ep.Epoller_Update(_sk.get_sockfd(), EPOLL_CTL_ADD, EPOLLIN);
    }

    void event_handler(struct epoll_event* ee_arr_ptr, int r_num)
    {
        for(int i = 0; i < r_num; ++i)
        {
            if(ee_arr_ptr[i].events & EPOLLIN)
            {
                if(ee_arr_ptr[i].data.fd == _sk.get_sockfd())
                {
                    std::cout << "get a new accept" << std::endl;
                    std::string clientip;
                    int16_t clientport = 0;
                    int ret_ap_fd = _sk.my_accept(clientip, clientport);
                    if(ret_ap_fd < 0)
                    {
                        perror("my_accept");
                    }
                    else
                    {
                        _ep.Epoller_Update(ret_ap_fd, EPOLL_CTL_ADD, EPOLLIN);
                    }
                }
                else
                {
                    char buffer[1024] = {0};
                    ssize_t n = read(ee_arr_ptr[i].data.fd, buffer, sizeof(buffer));
                    if(n < 0)
                    {
                        perror("read");
                    }
                    else if(n == 0)
                    {
                        std::cout << "fd " << ee_arr_ptr[i].data.fd << " is closed, close it and back." << std::endl;
                        _ep.Epoller_Update(ee_arr_ptr[i].data.fd, EPOLL_CTL_DEL, 0);
                        close(ee_arr_ptr[i].data.fd); // 先删除再close，防止报错
                    }
                    else
                    {
                        write(ee_arr_ptr[i].data.fd, buffer, n);
                    }
                }
            }
        }
    }

    void start()
    {
        struct epoll_event ee_arr[1024] = {0};
        while(1)
        {
            int n = _ep.Epoller_wait(ee_arr, sizeof(ee_arr));
            if(n < 0)
            {
                perror("Epoller_wait");
            }
            else if(n == 0)
            {
                std::cout << "time out" << std::endl;
            }
            else
            {
                event_handler(ee_arr, n);
            }
            sleep(1);
        }
    }
private:
    sock _sk;
    Epoller _ep;
};